package org.dromara.workflow.flowable.cmd;

import cn.hutool.core.collection.CollUtil;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
import org.flowable.engine.impl.util.CommandContextUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.dromara.workflow.common.constant.FlowConstant.NUMBER_OF_INSTANCES;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：串行加签
 */
/**
 * AddSequenceMultiInstanceCmd类实现了Command接口，用于添加序列的多实例命令
 * 该命令用于在某个序列中添加多个实例，是一个操作序列的操作命令
 */
public class AddSequenceMultiInstanceCmd implements Command<Void> {

    /**
     * 执行id
     */
    private final String executionId;

    /**
     * 会签人员集合KEY
     */
    private final String assigneeList;

    /**
     * 加签人员
     */
    private final List<Long> assignees;

    /**
     * AddSequenceMultiInstanceCmd类的构造函数
     * 该构造函数用于初始化命令对象，以便在流程中添加多人串行任务实例
     *
     * @param executionId 流程实例的唯一标识符，用于标识需要操作的流程实例
     * @param assigneeList 以字符串形式提供的多人任务执行者列表，用于定义任务将分配给哪些执行者
     * @param assignees 执行者列表，包含具体的执行者ID，这些ID与系统中的用户相对应
     */
    public AddSequenceMultiInstanceCmd(String executionId, String assigneeList, List<Long> assignees) {
        // 初始化流程实例ID
        this.executionId = executionId;
        // 初始化执行者列表字符串
        this.assigneeList = assigneeList;
        // 初始化执行者ID列表
        this.assignees = assignees;
    }

    /**
     * 执行多实例任务分配逻辑的方法
     * 该方法根据当前执行实体的变量信息，更新多实例任务的总数，并添加新的任务执行者到分配列表中
     *
     * @param commandContext 命令上下文，提供执行环境和资源访问
     * @return 返回null，表示此方法不返回具体结果
     */
    @Override
    public Void execute(CommandContext commandContext) {
        // 获取执行实体管理器
        ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager();
        // 根据执行ID查找执行实体
        ExecutionEntity entity = executionEntityManager.findById(executionId);
        // 多实例任务总数加 assignees.size()
        if (entity.getVariable(NUMBER_OF_INSTANCES) instanceof Integer nrOfInstances) {
            entity.setVariable(NUMBER_OF_INSTANCES, nrOfInstances + assignees.size());
        }
        // 设置流程变量
        if (entity.getVariable(assigneeList) instanceof List<?> userIds) {
            CollUtil.addAll(userIds, assignees);
            Map<String, Object> variables = new HashMap<>(16);
            variables.put(assigneeList, userIds);
            entity.setVariables(variables);
        }
        return null;
    }
}
